
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'package:eq/native/constants.dart';
import 'package:eq/src/core.dart';
import 'package:eq/src/interface.dart';
import 'package:eq/src/interpreter.dart';
import 'package:eq/src/utils.dart';
/// EQ 语言主文件
class ScriptResult implements Exception {
  final int code;
  final String? message;
  final dynamic data;

  const ScriptResult({required this.code, this.message, this.data});

  @override
  String toString() {
    return 'code:$code\n message:$message\n data:$data';
  }
}

class ScriptParams {
  ///线程的消息发送端口
  final SendPort? sendPort;

  ///脚本路径
  final String script;

  ///运行脚本的参数
  final List arg;

  ///主线程和线程通信结构
  final ScriptResult? result;

  const ScriptParams(
      {required this.script, required this.arg, this.sendPort, this.result});

  ScriptParams copyWith(
          {String? script,
          List? arg,
          SendPort? sendPort,
          ScriptResult? result}) =>
      ScriptParams(
          script: script ?? this.script,
          sendPort: sendPort ?? this.sendPort,
          arg: arg ?? this.arg,
          result: result);

  @override
  String toString() {
    return 'script:$script\n arg:$arg\n result:$result';
  }
}

late final ScriptParams _params;
late final StreamSubscription streamSubscription;
runScript(ScriptParams params) {
  exitIso = true;
  final ReceivePort port = ReceivePort();
  _params = ScriptParams(
      script: params.script, arg: params.arg, sendPort: params.sendPort);

  /// 0:成功退出
  /// 1:异常退出
  /// 2:纯日志
  /// 3... 其它操作
  streamSubscription = port.listen((message) {
    assert(message is ScriptResult, 'iso message must be ScriptResult type');
    message as ScriptResult;
    print(message);
  });

  ///发送第一波参数
  _params.sendPort?.send(_params.copyWith(
    result: ScriptResult(
        code: 2,
        message: 'script running and connected ok',
        data: port.sendPort),
  ));

  ///工程分析
  ///
  ///目录工程，分析配置文件eq.json,找主脚本以及增加一些定义信息.
  ///注意文件后缀eq
  File f = File(params.script);

  Interpreter.getInstance().proDir = f.parent.path; //设置项目基本属性时使用filepath
  Interpreter.getInstance().mainModule = main_module;

  ///创建解释器并进行词法分析
  ///进行语法分析
  //loadModule(Interpreter.getInstance().mainModule);
  interpreterCompile(f, Interpreter.getInstance().mainModule);
  Interpreter.getInstance().module[main_module]!.setLoad = true;

  ///开始运行语句
  Interpreter.getInstance().module[main_module]!.variable.add(Variable(
      'environment', Value(ValueType.ARRAY_VALUE, params.arg),
      isFixed: true));
  loadModule(eq_core);
  StatementResult result = interpreterRun(
      Interpreter.getInstance().mainModule,
      Interpreter.getInstance()
          .module[Interpreter.getInstance().mainModule]!
          .statementList);
  if (result.type == StatementResultType.ERROR_RUNTIME_RESULT) {
    exitApp(result.error!, 1);
  }
  exitApp('exit succeed', 0);
}

void exitScript(String msg, int code) {
  streamSubscription.cancel();
  Isolate.exit(_params.sendPort,
      _params.copyWith(result: ScriptResult(code: code, message: msg)));
}

void sendToHost(ScriptResult result) {
  _params.sendPort?.send(_params.copyWith(result: result));
}
